using System.Linq.Expressions;
using AutoMapper;
using AutoMapper.EquivalencyExpression;

namespace WL.Think.Abp.AutoMapper;

public abstract class AutoMapperProfile : Profile
{
    protected AutoMapperProfile()
    {
        Mapping();
    }

    public abstract void Mapping();

    /// <summary>
    /// 实体映射
    /// 默认清空下映射到现有集合时，将首先清除目标集合，这时对于EFCore来说就是全新的对象，
    /// 那么其如果原来已经有对应实体已经在状态中Tracking，这时就会报实体更新冲突。
    /// 为了解决这个问题，可以引入 AutoMapper.Collection，但是它需要配置两个列表的元素等价关系，
    /// 这样这块包会根据这个等价关系来判断哪些元素是删除，哪些是更新，哪些是新增，而不是全部清空。
    /// 初次之外，还需要配置 context.Services.AddAutoMapper(x => x.AddCollectionMappers()); 
    /// </summary>
    /// <typeparam name="TSource">原有实体</typeparam>
    /// <typeparam name="TTarget">目标实体</typeparam>
    /// <param name="expression">元素的等价关系</param>
    /// <returns></returns>
    protected IMappingExpression<TSource, TTarget> Map<TSource, TTarget>(Expression<Func<TSource, TTarget, bool>>? expression = null)
    {
        var mappingExpression = CreateMap<TSource, TTarget>();
        if(expression != null)
        {
            mappingExpression.EqualityComparison(expression);
        }
        return mappingExpression;
    }
}
